package typeinfo;

import java.util.Random;

/**
 * @author Mr.Sun
 * @date 2022年02月18日 20:54
 *
 * 当使用“.class”来创建对Class对象的引用时，不会自动地初始化该Class对象。
 * 为了使用类而做的准备工作实际包含三个步骤：
 * 1.加载
 * 2.链接
 * 3.初始化
 *
 * 初始化被延迟到了对静态方法（构造器隐式地是静态的）或者非常数静态域进行首次引用时才执行
 */

class Initable {
    // 编译期常量，Initable不需要被初始化就可以读取
    static final int staticFinal = 47;
    static final int staticFinal2 = ClassInitialization.rand.nextInt(1000);
    static {
        System.out.println("Initializing Initable");
    }
}

class Initable2 {
    static int staticNonFinal = 147;
    static {
        System.out.println("Initializing Initable2");
    }
}

class Initable3 {
    static int staticNonFinal = 74;
    static {
        System.out.println("Initializing Initable3");
    }
}

public class ClassInitialization {
    public static Random rand = new Random(47);

    public static void main(String[] args) throws Exception {
        Class initable = Initable.class;
        System.out.println("After creating Initable ref");

        // 编译期常量，这个值不需要对Initable类初始化就可以被读取
        System.out.println(Initable.staticFinal);

        // 对Initable.staticFinal2的访问将强制进行类得初始化，因为他不是一个编译器常量
        System.out.println(Initable.staticFinal2);

        // 如果一个static域不是final的，那么在对它访问时，总是要求被读取之前，要先进行链接（为这个域分配存储空间）和初始化（初始化该存储空间）
        System.out.println(Initable2.staticNonFinal);

        // Class.forName()立即就进行了初始化
        Class initable3 = Class.forName("typeinfo.Initable3");
        System.out.println("After creating Initable3 ref");
        System.out.println(Initable3.staticNonFinal);
    }
}/* output:
After creating Initable ref
47
Initializing Initable
258
Initializing Initable2
147
Initializing Initable3
After creating Initable3 ref
74
*/
